import * as THREE from "three";
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
class Base3d {
  constructor(selector, onFinish) {
    this.container = document.querySelector(selector);
    this.camera;
    this.scene;
    this.renderer;
    this.model;
    this.panzi;
    this.animateAction;
    this.mixer;
    this.clock = new THREE.Clock();
    this.onFinish = onFinish;
    this.progressFn;
    this.init();
    this.animate();
  }
  init() {
    this.initScene();
    this.initCamera();
    this.initRenderer();
    this.addMesh();
    // this.initControls();
    window.addEventListener("resize", this.onWindowResize.bind(this));
    // 监听滚轮事件
    window.addEventListener("mousewheel", this.onMouseWheel.bind(this));
  }
  initScene() {
    this.scene = new THREE.Scene();
    this.setEnvMap("000");
  }
  initCamera() {
    this.camera = new THREE.PerspectiveCamera(
      45,// 俯视45°
      window.innerWidth / window.innerHeight,// 相机宽高比例
      0.25, // 最近观看距离
      200   // 最远观看距离
    );
    this.camera.position.set(-1.8, 0.6, 2.7);
  }
  initRenderer() {
    this.renderer = new THREE.WebGLRenderer({antialias: true }); // 加入抗锯齿
    this.renderer.setPixelRatio(window.devicePixelRatio); // 屏幕像素比
    this.renderer.setSize(window.innerWidth, window.innerHeight); // 渲染尺寸大小
    this.renderer.toneMapping = THREE.ACESFilmicToneMapping;// 色调映射
    this.renderer.toneMappingExposure = 2;
    this.container.appendChild(this.renderer.domElement);
  }
  initControls() {
    this.conrtols = new OrbitControls(this.camera, this.renderer.domElement);
  }
  setEnvMap(hdr) {
    new RGBELoader().setPath("./files/hdr/").load(hdr + ".hdr", texure => {
      this.scene && this.scene.removeFromParent();
      texure.mapping = THREE.EquirectangularReflectionMapping;
      this.scene.background = texure; // 背景设置纹理
      this.scene.environment = texure;  // 环境设置纹理
    }, e => {
      // console.log("模式加载进度：", e);
      this.progressFn(e);
    })
  }
  setModel(modelName) {
    return new Promise((resolve, reject) => {
      const loader = new GLTFLoader().setPath("files/gltf/");
      loader.load(modelName, gltf => {
        this.model && this.model.removeFromParent();// 删除之前存在的模型
        this.model = gltf.scene.children[0];
        this.scene.add(this.model);
        if ("bag2.glb" === modelName && !this.panzi) {
          this.panzi = gltf.scene.children[4];
          this.scene.add(gltf.scene);
          // 将摄像头设置为模型摄像头
          this.camera = gltf.cameras[0];
          // 调用动画
          this.mixer = new THREE.AnimationMixer(gltf.scene.children[0]);
          this.animateAction = this.mixer.clipAction(gltf.animations[0]);
          // 设置动画播放时长
          this.animateAction.setDuration(20).setLoop(THREE.LoopOnce);
          // 设置播放完成之后停止
          this.animateAction.clampWhenFinished = true;
          // this.animateAction.play()
          // 设置灯光亮度
          this.spotlight1 = gltf.scene.children[1].children[0]
          this.spotlight1.intensity = 1;
          this.spotlight2 = gltf.scene.children[2].children[0]
          this.spotlight2.intensity = 1;
          this.spotlight3 = gltf.scene.children[3].children[0]
          this.spotlight3.intensity = 1;
        }
        resolve(modelName + "模型添加成功！");
      }, e => {
        // console.log("模式加载进度：", e);
        this.progressFn(e);
      });
    });
  }
  async addMesh() {
    const res = await this.setModel("bag2.glb");
    this.onFinish(res);
  }
  render() {
    const delta = this.clock.getDelta();
    this.mixer && this.mixer.update(delta);
    this.renderer.render(this.scene, this.camera);
    
  }
  animate() {
    this.renderer.setAnimationLoop(this.render.bind(this));
  }
  onProgress(fn) {
    this.progressFn = fn;
  }
  onWindowResize() {
    this.camera.aspect = window.innerWidth / window.innerHeight;
    this.camera.updateProjectionMatrix();
    this.renderer.setSize(window.innerWidth, window.innerHeight)
  }
  onMouseWheel(e) {
    // console.log(this.animateAction);
    const timeScale = e.deltaY > 0 ? 1 : -1;
    this.animateAction.setEffectiveTimeScale(timeScale);
    this.animateAction.paused = false;
    this.animateAction.play();
    if (this.timeoutid) clearTimeout(this.timeoutid);
    this.timeoutid = setTimeout(() => {
      this.animateAction.halt(0.5);
    }, 300);
  }
}

export default Base3d;
